package com.lyz.redis.service;

import io.lettuce.core.ScanCursor;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;

import java.util.Collection;
import java.util.List;
import java.util.Set;

public class SetRedisService<V> extends RedisService<String,V>{

    public SetRedisService(RedisTemplate<String,V> redisTemplate) {
        super(redisTemplate);
    }


    /**
     * 保存Set集合
     * @param k 键
     * @param vs 数组值
     * @return 设置数量
     */
    @SafeVarargs
    public final Long set(String k, V... vs){
        return redisTemplate.opsForSet().add(k, vs);
    }

    /**
     * 获取集合的成员数
     * @param k
     * @return
     */
    public Long size(String k){
        return this.redisTemplate.opsForSet().size(k);
    }

    /**
     * 返回第一个集合与其他集合之间的差异
     * @param k key
     * @param keys key集合
     * @return 差集
     */
    public Set<V> difference(String k, Collection<String> keys){
        return this.redisTemplate.opsForSet().difference(k,keys);
    }

    /**
     * 返回给定所有集合的差集
     * @param keys
     * @return
     */
    public Set<V> difference(Collection<String> keys){
        return this.redisTemplate.opsForSet().difference(keys);
    }

    public Set<V> difference(String k,String otherKey){
        return this.redisTemplate.opsForSet().difference(k,otherKey);
    }

    /**
     * 返回给定所有集合的差集并存储在 destination 中
     * @param keys
     * @return
     */
    public Long differenceAndStore(Collection<String> keys,String destination){
        return this.redisTemplate.opsForSet().differenceAndStore(keys,destination);
    }

    /**
     * 返回给定所有集合的交集
     * @param keys key集合
     * @return 交集
     */
    public Set<V> intersect(Collection<String> keys){
        return this.redisTemplate.opsForSet().intersect(keys);
    }


    /**
     * 返回给定所有集合的交集并存储在 destination 中
     * @param k
     * @param keys
     * @param destination
     * @return
     */
    public Long intersectAndStore(String k,Collection<String> keys,String destination){
        return this.redisTemplate.opsForSet().intersectAndStore(k,keys,destination);
    }

    /**
     * 返回指定key之间的交集
     * @param keys key集合
     * @return 交集
     */
    public Set<V> union(Collection<String> keys){
        return this.redisTemplate.opsForSet().union(keys);
    }

    /**
     * 返回key 和 keys的交集
     * @param k key
     * @param keys other keys
     * @return 交集
     */
    public Set<V> union(String k,Collection<String> keys){
        return this.redisTemplate.opsForSet().union(k,keys);
    }

    /**
     * 返回交集成员数
     * @param key
     * @param keys
     * @param des
     * @return
     */
    public Long unionAndStore(String key,Collection<String> keys,String des){
        return this.redisTemplate.opsForSet().unionAndStore(key,keys,des);
    }

    /**
     * 返回指定key的集合数，并把集合存储到新的des key上
     * @param keys
     * @param des
     * @return
     */
    public Long unionAndStore(Collection<String> keys,String des){
        return this.redisTemplate.opsForSet().unionAndStore(keys,des);
    }

    /**
     * 返回指定key的集合数，并把集合存储到新的des key上
     * @param k1
     * @param k2
     * @param des
     * @return
     */
    public Long unionAndStore(String k1,String k2,String des){
        return this.redisTemplate.opsForSet().unionAndStore(k1,k2,des);
    }

    /**
     * 判断 member 元素是否是集合 key 的成员
     * @param k
     * @param v
     * @return
     */
    public Boolean isMember(String k,Object v){
        return this.redisTemplate.opsForSet().isMember(k,v);
    }

    /**
     * 返回集合中的所有成员
     * @param k key
     * @return Set<V>
     */
    public Set<V> members(String k){
        return this.redisTemplate.opsForSet().members(k);
    }

    /**
     * 将 member 元素从 source 集合移动到 destination 集合
     * @param source member 原所属key
     * @param destination  目标key
     * @return 移动是否完成
     */
    public Boolean move(String source,V member,String destination){
        return this.redisTemplate.opsForSet().move(source,member,destination);
    }

    /**
     * 移除集合中一个或多个成员
     * @param k redis key
     * @param v V[]
     * @return 移除数量
     */
    @SafeVarargs
    public final Long remove(String k, V... v){
        return this.redisTemplate.opsForSet().remove(k, (Object[]) v);
    }

    /**
     * 随机返回一个成员
     * @param k reids key
     * @return V
     */
    public V randomMember(String k){
        return this.redisTemplate.opsForSet().randomMember(k);
    }

    /**
     * 指定随机返回一个或多个成员
     * @param k redis key
     * @param count 成员个数
     * @return  {@code List<V>}
     */
    public List<V> randomMember(String k, Long count){
        return this.redisTemplate.opsForSet().randomMembers(k,count);
    }

    /**
     * 逐个弹出Set集合值，遵循先进先出原则
     * @param k 键
     * @return v
     */
    public V pop(String k){
        return redisTemplate.opsForSet().pop(k);
    }

    /**
     * 遍历key 的值集合
     * @param k Redis key
     * @param count 遍历数量
     * @param pattern 正则匹配，使用通配符
     * @param handler 遍历值处理器
     */
    public void scan(String k,Long count,String pattern,ScanHandler<V> handler){
        ScanOptions options = ScanOptions.scanOptions().count(count).match(pattern).build();
        Cursor<V> cursor = this.redisTemplate.opsForSet().scan(k, options);
        while (cursor.hasNext()){
            V v = cursor.next();
            handler.handle(v);
        }
        cursor.close();
    }

    public interface ScanHandler<V>{
        void handle(V v);
    }
}
